package com.tanhua.manage.service;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tanhua.manage.domain.AnalysisByDay;
import com.tanhua.manage.mapper.AnalysisByDayMapper;
import com.tanhua.manage.mapper.LogMapper;
import com.tanhua.manage.utils.ComputeUtil;
import com.tanhua.manage.vo.AnalysisSummaryVo;
import com.tanhua.manage.vo.LastYear;
import com.tanhua.manage.vo.ThisYear;
import com.tanhua.manage.vo.UsersVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 每日分析 服务类
 *
 * @author jw
 */
@Service
public class AnalysisByDayService extends ServiceImpl<AnalysisByDayMapper, AnalysisByDay> {
    @Autowired(required = false)
    private AnalysisByDayMapper analysisByDayMapper;
    @Autowired(required = false)
    private LogMapper logMapper;

    public ResponseEntity<Object> summary() {
        // 封装返回结果
        AnalysisSummaryVo vo = new AnalysisSummaryVo();
        // select sum(num_registered) num_registered from tb_analysis_by_day
        AnalysisByDay analysisByDay = query().select("sum(num_registered) num_registered").one();
        Integer numRegistered = analysisByDay.getNumRegistered();

        // 2.查询今日新增、今日活跃、今日登录数
        // select * from tb_analysis_by_day where record_date = '2021-03-06'

        String now = new SimpleDateFormat("yyyy-MM-dd").format(System.currentTimeMillis());
        AnalysisByDay recodeToday = query().eq("record_date", now).one();
        if (recodeToday != null) {
            // 今日新增
            Integer numRegisteredToday = recodeToday.getNumRegistered();
            // 今日活跃
            Integer numActiveToday = recodeToday.getNumActive();
            // 今日登录
            Integer numLoginToday = recodeToday.getNumLogin();


            // 3.查询昨日新增、昨日活跃、昨日登录数
            // select * from tb_analysis_by_day where record_date = '2021-03-05'
            AnalysisByDay recodeYes = query().eq("record_date", ComputeUtil.offsetDay(new Date(), -1)).one();
            if (recodeYes != null) {
                // 昨日新增
                Integer numRegisteredYes = recodeYes.getNumRegistered();
                // 昨日活跃
                Integer numActiveYes = recodeYes.getNumActive();
                // 昨日登录
                Integer numLoginYes = recodeYes.getNumLogin();


                // 4.查询过去七天活跃、30天活跃数
                AnalysisByDayMapper baseMapper = getBaseMapper();
                Long day7 = baseMapper.findNumActiveByDate(ComputeUtil.offsetDay(new Date(), -7), now);
                Long day30 = baseMapper.findNumActiveByDate(ComputeUtil.offsetDay(new Date(), -30), now);

                // 设置累计用户
                vo.setCumulativeUsers(Long.valueOf(numRegistered));

                // 设置今日新增
                vo.setNewUsersToday(Long.valueOf(numRegisteredToday));
                // 设置今日登录
                vo.setLoginTimesToday(Long.valueOf(numLoginToday));
                // 设置今日活跃
                vo.setActiveUsersToday(Long.valueOf(numActiveToday));

                // 设置过去7天活跃
                vo.setActivePassWeek(Long.valueOf(day7.intValue()));
                // 设置过去30天活跃
                vo.setActivePassMonth((long) day30.intValue());

                // 设置新增用户涨跌率
                vo.setNewUsersTodayRate(ComputeUtil.computeRate(numRegisteredToday, numRegisteredYes));
                // 设置登录次数涨跌率
                vo.setLoginTimesTodayRate(ComputeUtil.computeRate(numLoginToday, numLoginYes));
                // 设置活跃用户涨跌率
                vo.setActiveUsersTodayRate(ComputeUtil.computeRate(numActiveToday, numActiveYes));
            }
        }
        return ResponseEntity.ok(vo);
    }

    /**
     * 分析用户活跃数据
     */
    public void anasysis() {
        //hutool工具类获得当前日期 yyyy-MM-dd
        String today = DateUtil.today();
        //MP查询当天的统计数据
        QueryWrapper<AnalysisByDay> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("record_date", today);
        AnalysisByDay todayAnalysisDate = analysisByDayMapper.selectOne(queryWrapper);
        //如果当天统计数据没有新建一条
        if (todayAnalysisDate == null) {
            todayAnalysisDate = new AnalysisByDay();
            // hutool工具类, 解析当前时间 对象  yyyy-MM-dd
            Date nowDate = DateUtil.parse(today);
            todayAnalysisDate.setCreated(nowDate);
            todayAnalysisDate.setUpdated(nowDate);
            todayAnalysisDate.setRecordDate(nowDate);
            analysisByDayMapper.insert(todayAnalysisDate);
        }
        //hutool工具类获得昨天日期 yyyy-MM-dd
        DateTime yesterday = DateUtil.yesterday();
        //  统计log表中，今日注册人数
        Long registeredNum = logMapper.countNumRegistered(today, "0102");
        //  统计log表中，登陆次数
        Long loginNum = logMapper.countNumLogin(today, "0101");
        //  统计log表中，活跃用户数
        Long activeNum = logMapper.countNumActive(today);
        //  统计log表中，次日留存用户数
        Long retention1d = logMapper.countNumRetention1d(today, yesterday.toString());

        // 5.封装数据，更新统计分析表
        todayAnalysisDate.setNumRegistered(registeredNum.intValue());
        todayAnalysisDate.setNumLogin(loginNum.intValue());
        todayAnalysisDate.setNumActive(activeNum.intValue());
        todayAnalysisDate.setNumRetention1d(retention1d.intValue());
        todayAnalysisDate.setUpdated(new Date());
        analysisByDayMapper.updateById(todayAnalysisDate);
    }


    public ResponseEntity<Object> users(String type, Long startDateStr, Long endDateStr) {
        //要返回的vo
        UsersVo usersVo = new UsersVo();
        List<ThisYear> thisYears = new ArrayList<>();
        List<LastYear> lastYears = new ArrayList<>();
        //转换date
        DateTime startDate = DateUtil.date(startDateStr);
        DateTime endDate = DateUtil.date(endDateStr);
        //业务判断 年处理
        int startYear = DateUtil.year(startDate);
        int endYear = DateUtil.year(endDate);
        //去年时间
        DateTime lastStartYear = DateUtil.offsetMonth(startDate, -12);
        DateTime lastEndYear = DateUtil.offsetMonth(endDate, -12);
        int overStartYear = DateUtil.year(lastStartYear);
        int overEndYear = DateUtil.year(lastEndYear);

        if (endYear - startYear > 1) {
            return ResponseEntity.status(401).body("仅支持一年内的查询");
        }
        //月处理 从0开始计数
        int startMonth = DateUtil.month(startDate);
        int endMonth = DateUtil.month(endDate);
        //日处理
        Integer startDay = Integer.parseInt(DateUtil.format(startDate, "dd"));
        Integer endDay = Integer.parseInt(DateUtil.format(endDate, "dd"));
        for (int i = startMonth + 1; i <= endMonth + 1; i++) {

            //开始月份
            if (i == startMonth + 1) {
                //按月查询,拼接日期
                String start = startYear + "-" + i + "-" + startDay;
                String lastStart = overStartYear + "-" + i + "-" + startDay;

                String end = null;
                String lastEnd = null;
                //判断有没有31号
                int[] arr = {1, 3, 5, 7, 8, 10, 12};
                if (exist(arr, startMonth + 1)) {
                    end = startYear + "-" + i + "-" + "31";
                    lastEnd = overStartYear + "-" + i + "-" + "31";
                } else {
                    end = startYear + "-" + i + "-" + "30";
                    lastEnd = overStartYear + "-" + i + "-" + "30";
                }
                //101 新增 102 活跃用户 103 次日留存率
                Integer result = 0;
                Integer lastResult = 0;

                switch (type) {
                    case "101":
                        result = logMapper.countNumRegisteredByMonth(start, end);
                        lastResult = logMapper.countNumRegisteredByMonth(lastStart, lastEnd);
                        break;
                    case "102":
                        result = logMapper.countNumActiveByMonth(start, end);
                        lastResult = logMapper.countNumActiveByMonth(lastStart, lastEnd);
                        break;
                    case "103":
                        result = logMapper.countNumRetention1dByMonth(start, end);
                        lastResult = logMapper.countNumRetention1dByMonth(lastStart, lastEnd);
                        break;
                    default:
                        result = 0;
                        lastResult = 0;
                }
                //添加结果
                thisYears.add(new ThisYear(String.valueOf(i), result));
                lastYears.add(new LastYear(String.valueOf(i), lastResult));
            }
            //中间月份
            if (i > startMonth + 1 && i < endMonth + 1) {
                String start = startYear + "-" + i + "-01";
                String lastStart = overStartYear + "-" + i + "-01";
                String end = null;
                String lastEnd = null;
                int[] arr = {1, 3, 5, 7, 8, 10, 12};
                if (exist(arr, startMonth + 1)) {
                    end = startYear + "-" + i + "-" + "30";
                    lastEnd = overStartYear + "-" + i + "-" + "31";
                } else {
                    end = startYear + "-" + i + "-" + "31";
                    lastEnd = overStartYear + "-" + i + "-" + "31";
                }
                //101 新增 102 活跃用户 103 次日留存率
                Integer result = 0;
                Integer lastResult = 0;
                switch (type) {
                    case "101":
                        result = logMapper.countNumRegisteredByMonth(start, end);
                        lastResult = logMapper.countNumRegisteredByMonth(lastStart, lastEnd);
                        break;
                    case "102":
                        result = logMapper.countNumActiveByMonth(start, end);
                        lastResult = logMapper.countNumActiveByMonth(lastStart, lastEnd);
                        break;
                    case "103":
                        result = logMapper.countNumRetention1dByMonth(start, end);
                        lastResult = logMapper.countNumRetention1dByMonth(lastStart, lastEnd);
                        break;
                    default:
                        result = 0;
                }
                //添加结果
                thisYears.add(new ThisYear(String.valueOf(i), result));
                lastYears.add(new LastYear(String.valueOf(i), lastResult));
            }

            //结束月份
            if (i == endMonth + 1) {
                String start = startYear + "-" + i + "-01";
                String lastStart = overStartYear + "-" + i + "-01";
                String end = startYear + "-" + i + "-" + endDay;
                String lastEnd = overStartYear + "-" + i + "-" + endDay;

                //101 新增 102 活跃用户 103 次日留存率
                Integer result = 0;
                Integer lastResult = 0;
                switch (type) {
                    case "101":
                        result = logMapper.countNumRegisteredByMonth(start, end);
                        lastResult = logMapper.countNumRegisteredByMonth(lastStart, lastEnd);
                        break;
                    case "102":
                        result = logMapper.countNumActiveByMonth(start, end);
                        lastResult = logMapper.countNumActiveByMonth(lastStart, lastEnd);
                        break;
                    case "103":
                        result = logMapper.countNumRetention1dByMonth(start, end);
                        lastResult = logMapper.countNumRetention1dByMonth(lastStart, lastEnd);
                        break;
                    default:
                        result = 0;
                }
                //添加结果
                thisYears.add(new ThisYear(String.valueOf(i), result));
                lastYears.add(new LastYear(String.valueOf(i), lastResult));
            }
        }
        usersVo.setThisYear(thisYears);
        usersVo.setLastYear(lastYears);
        return ResponseEntity.ok(usersVo);
    }

    /**
     * 判断key在数组arr中是否存在
     *
     * @param arr 数组
     * @param key 待查找值
     * @return key在数组arr中是否存在，true：存在，false：不存在
     */
    public static boolean exist(int[] arr, int key) {
        for (int i = 0; i < arr.length; i++) {
            if (arr[i] == key) {
                return true;
            }
        }
        return false;
    }
}
